import axios from 'axios'
import type { AxiosRequestConfig, Canceler } from 'axios'
import router from '@/router'
import useGlobalStore from '@/store/modules/global'

// * 声明一个 Map 用于存储每个请求的标识 和 取消函数
let pendingMap = new Map<string, Canceler>()

// * 序列化参数
const getPendingUrl = (config: AxiosRequestConfig) => {
  return [config.method, config.url, JSON.stringify(config.data), JSON.stringify(config.params)].join('&')
}

/**
 * @description 请求自定义
 */
export class AxiosCanceler {
  /**
   * @description: 添加请求
   * @param {Object} config
   * @return void
   */
  addPending(config: AxiosRequestConfig) {
    // * 在请求开始前，对之前的请求做检查取消操作
    this.removePending(config)
    const url = getPendingUrl(config)
    config.cancelToken =
      config.cancelToken ||
      new axios.CancelToken(cancel => {
        if (!pendingMap.has(url)) {
          // 如果 pending 中不存在当前请求，则添加进去
          pendingMap.set(url, cancel)
        }
      })
  }

  /**
   * @description: 移除请求
   * @param {Object} config
   */
  removePending(config: AxiosRequestConfig) {
    const url = getPendingUrl(config)

    if (pendingMap.has(url)) {
      // 如果在 pending 中存在当前请求标识，需要取消当前请求，并且移除
      const cancel = pendingMap.get(url)
      cancel && cancel()
      pendingMap.delete(url)
    }
  }

  /**
   * @description: 清空所有pending
   */
  removeAllPending() {
    pendingMap.forEach(cancel => {
      cancel && cancel()
    })
    pendingMap.clear()
  }

  /**
   * @description: 重置
   */
  reset(): void {
    pendingMap = new Map<string, Canceler>()
  }
}

/**
 * @description: 校验网络请求状态码
 * @param {Number} status
 * @return void
 */
export const checkStatus = (status: string): void => {
  // 全局缓存
  const globalStore = useGlobalStore()
  let message = ''
  switch (status) {
    case '401':
      message = '登录信息已过期，请重新登录'
      globalStore.setToken('')
      router.push('/')
      break
    case '403':
      message = '当前账号无权限访问！'
      break
    case '404':
      message = '你所访问的资源不存在！'
      break
    case '405':
      message = '请求方式错误！请您稍后重试'
      break
    case '408':
      message = '请求超时！请您稍后重试'
      break
    case '500':
      message = '服务异常！'
      break
    case '502':
      message = '网关错误！'
      break
    case '503':
      message = '服务不可用！'
      break
    case '504':
      message = '网关超时！'
      break
    default:
      message = '操作过于频繁！'
  }
  ElMessage.error(message)
}

// * 请求枚举配置
/**
 * @description：请求配置
 */
export enum ResultEnum {
  SUCCESS = '000',
  ERROR = 500,
  OVERDUE = '2031',
  TIMEOUT = 20000,
  TYPE = 'success'
}

/**
 * @description：请求方法
 */
export enum RequestEnum {
  GET = 'GET',
  POST = 'POST',
  PATCH = 'PATCH',
  PUT = 'PUT',
  DELETE = 'DELETE'
}

/**
 * @description：常用的contentTyp类型
 */
export enum ContentTypeEnum {
  // json
  JSON = 'application/json;charset=UTF-8',
  // text
  TEXT = 'text/plain;charset=UTF-8',
  // form-data 一般配合qs
  FORM_URLENCODED = 'application/x-www-form-urlencoded;charset=UTF-8',
  // form-data 上传
  FORM_DATA = 'multipart/form-data;charset=UTF-8'
}
